/****************************************************************************
 ** Copyright (c) quickfixengine.org  All rights reserved.
 **
 ** This file is part of the QuickFIX FIX Engine
 **
 ** This file may be distributed under the terms of the quickfixengine.org
 ** license as defined by quickfixengine.org and appearing in the file
 ** LICENSE included in the packaging of this file.
 **
 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 **
 ** See http://www.quickfixengine.org/LICENSE for licensing information.
 **
 ** Contact ask@quickfixengine.org if any conditions of this licensing are
 ** not clear to you.
 **
 ****************************************************************************/

#ifdef _MSC_VER
#include "stdafx.h"
#else
#include "config.h"
#endif
#include "CallStack.h"

#include "FASTParser.h"
#include "Message.h"
#include "Utility.h"
#include "FieldConvertors.h"
#include <algorithm>

namespace FIX {
Mutex FASTParser::iq_mutex;
bool FASTParser::extractLength(int& length, std::string::size_type& pos,
		const std::string& buffer) throw (MessageParseError) {
	QF_STACK_PUSH(FASTParser::extractLength)

	if (!buffer.size())
		return false;

	std::string::size_type startPos = buffer.find("\0019=", 0);
	if (startPos == std::string::npos)
		return false;
	startPos += 3;
	std::string::size_type endPos = buffer.find("\001", startPos);
	if (endPos == std::string::npos)
		return false;

	std::string strLength(buffer, startPos, endPos - startPos);

	try {
		length = IntConvertor::convert(strLength);
		if (length < 0)
			throw MessageParseError();
	} catch (FieldConvertError&) {
		throw MessageParseError();
	}

	pos = endPos + 1;
	return true;

QF_STACK_POP}

void FASTParser::decodeTags( int tid, std::stringstream & ss, std::string msg_type )
{
FastTagVector tags = m_dataDictionary->getFieldTag( tid );
u32 ku = 0;
i32 k = 0;
double d = 0;
i64 k64 = 0;
u64 ku64 = 0;
u8 v[1024];
for ( FastTagVector::iterator ii = tags.begin(); ii != tags.end(); ii++ )
{
	if ( ii->m_num == 9 || ii->m_num == 9999)
	{
		continue;
	}
	if ( ii->m_num == 10 )
	{
		ss << ii->m_num << "=9999\001";
		continue;
	}
	if ( ii->m_num == 35 )
	{
		ss << "9=9999\001" << "35=" << msg_type << "\001";
		continue;
	}
	memset(v, '\0', sizeof(v));
	switch( ii->m_type )
	{
		case eFAST_TYPE_ASCII:
		if ( iFast.decode_string (ii->m_tag, STR_ARGS (v)) > -1 )
		{
			ii->m_value = reinterpret_cast<char*>(v);
			ss << ii->m_num << "=" << v << "\001";
		}
		break;
		case eFAST_TYPE_I32:
		if ( iFast.decode_i32 (ii->m_tag, &k) > -1 )
		{
			sprintf(reinterpret_cast<char*>(v), "%d\0", k );
			ii->m_value = reinterpret_cast<char*>(v);
			ss << ii->m_num << "=" << ii->m_value << "\001";
		}
		break;
		case eFAST_TYPE_U32:
		if ( iFast.decode_u32 (ii->m_tag, &ku) > -1 )
		{
			sprintf(reinterpret_cast<char*>(v), "%d\0", ku );
			ii->m_value = reinterpret_cast<char*>(v);
			ss << ii->m_num << "=" << ii->m_value << "\001";
		}
		break;
		case eFAST_TYPE_GROUP:
		if( iFast.decode_group_count (ii->m_tag, &ku) > -1 )
		{
			sprintf(reinterpret_cast<char*>(v), "%d\0", ku );
			ii->m_value = reinterpret_cast<char*>(v);
			ss << ii->m_num << "=" << ii->m_value << "\001";
			for (unsigned int i = 0; i < ku; i++ )
			{
				FASTPMap tmap;
				iFast.backup_presence_map(tmap);
				iFast.reset_presence_map();
				if (iFast.decode_message (eFAST_BASE_TID) < 0)
				return;
				u32 templateID = 0;
				//a.decodeMsgLen (eFAST_MSG_TYPE, templateID); //simulate eFAST_MSG_TYPE
				if ( ii->get_ref_tid() == "none" )
				templateID = atoi(ii->get_ref_tid().c_str());
				else
				iFast.decode_u32 (eFAST_MSG_TYPE, &templateID);
				if ( templateID == (unsigned int)atoi(ii->get_ref_tid().c_str()) )
				{
					decodeTags( ii->get_num(), ss );
				}
				else
				{
					throw "Template not found:";
				}
				iFast.reset_presence_map();
				iFast.restore_presence_map(tmap);
			}
		}
		break;
		case eFAST_TYPE_DECMIAL:
		if( iFast.decode_double(ii->m_tag, &d) > -1 )
		{
			sprintf(reinterpret_cast<char*>(v), "%f\0", d );
			ii->m_value = reinterpret_cast<char*>(v);
			ss << ii->m_num << "=" << ii->m_value << "\001";
		}
		break;
		case eFAST_TYPE_UNICODE:
		if ( iFast.decode_string (ii->m_tag, STR_ARGS (v)) > -1 )
		{
			ii->m_value = reinterpret_cast<char*>(v);
			ss << ii->m_num << "=" << ii->m_value << "\001";
		}
		break;
		case eFAST_TYPE_I64:
		if ( iFast.decode_i64 (ii->m_tag, &k64) > -1 )
		{
			sprintf(reinterpret_cast<char*>(v), "%d\0", k64 );
			ii->m_value = reinterpret_cast<char*>(v);
			ss << ii->m_num << "=" << ii->m_value << "\001";
		}
		break;
		case eFAST_TYPE_U64:
		if ( iFast.decode_u64 (ii->m_tag, &ku64) > -1 )
		{
			sprintf(reinterpret_cast<char*>(v), "%d\0", ku64 );
			ii->m_value = reinterpret_cast<char*>(v);
			ss << ii->m_num << "=" << ii->m_value << "\001";
		}
		break;
		default:
		break;
	}
}
}

bool FASTParser::readMessage( std::string& str )
throw( MessageParseError )
{QF_STACK_PUSH(FASTParser::readMessage)

std::string msg_type;

//{
Locker l( iq_mutex );
if( iq.empty() ) return false;

const iMsg& msg = iq.front();
iFast.set_codec_input(const_cast<u8*>(msg.c_ustr()), msg.length() );
//}

iFast.reset_presence_map();

if (iFast.decode_message (eFAST_BASE_TID) < 0)
return false;

u32 tid = 0;
iFast.decode_u32 (eFAST_MSG_TYPE, &tid); //put it back once corrected in the back-end

TemplateId2Msg::iterator ii = m_TemplateId2Message->find(tid);
if ( ii == m_TemplateId2Message->end())
throw "Error, please define tid";

msg_type = ii->second;
std::stringstream ss;
if ( tid != 16002 && tid != 16003) //Hello & Alert Message
{
	//decodeTags( eFAST_HDR_TEMPLATE, ss, msg_type );
}

//Body part
decodeTags(tid, ss, msg_type);

if ( tid != 16002 && tid != 16003) //Hello & Alert Message
{
	//decodeTags(eFAST_TRL_TEMPLATE, ss, msg_type);
}

if (iFast.decode_message_end (eFAST_BASE_TID) < 0)
return false;

str = ss.str();
{
	Locker l( iq_mutex );
	iq.pop_front();
}
return true;
QF_STACK_POP

}

void FASTParser::readFromStream( int m_socket, sockaddr_in &addr) throw ( SocketRecvFailed )
{QF_STACK_PUSH(FASTParser::readFromStream)
// LENGTH + MAP + TEMPLATE + FIELDS . . .
//Group = COUNT + MAP + TEMPLATEID
//Yes, we can read without blocking
printf("socket:%d, addr:%p\n", m_socket, &addr);
socklen_t addrlen = sizeof(addr);
if (m_bufferSizeYetToRead =! 0) //Ignore this
{
	while ( m_lenSizeYetToRead < 5 )
	{
		int size = recvfrom( m_socket, m_sockbuffer + m_lenSizeYetToRead, 1, 0, (struct sockaddr*)&addr, &addrlen );
		//fprintf(stdout, m_sockbuffer + m_lenSizeYetToRead, size );
		if ( size <= 0 )
		{
			if ( size == -1 ) return;
			throw SocketRecvFailed( size );
		}
		if ((unsigned char)m_sockbuffer[m_lenSizeYetToRead] >= STOP_BIT)
		{
			m_sockbuffer[m_lenSizeYetToRead] &= VALUE_BIT;
			m_lenSizeYetToRead++;
			break;
		}
		m_lenSizeYetToRead++;
	}
	if ( m_lenSizeYetToRead > 4 )
	throw "Overlong for the message length";

	m_bufferSize = 0 - ((m_sockbuffer [0] & 0x00) != 0);

	for (int icnt = 0; icnt < m_lenSizeYetToRead; icnt ++)
	m_bufferSize = m_bufferSizeYetToRead = (m_bufferSizeYetToRead << 7) | m_sockbuffer [icnt];
	m_lenSizeYetToRead = 0;
}
m_bufferSize = 0; //TODO 64K --imporve it
m_bufferSizeYetToRead = m_bufferSize;

if ( m_bufferSizeYetToRead )
{
	int size = recvfrom( m_socket, m_sockbuffer , m_bufferSizeYetToRead, 0, (struct sockaddr*)&addr, &addrlen );
	if ( size <= 0 )
	{
		if ( size == -1 ) return;
		throw SocketRecvFailed( size );
	}
	//if ( size == m_bufferSizeYetToRead )
	{
		Locker l( iq_mutex );
		{
			iq.push_back(iMsg(m_sockbuffer, size ));
		}
		m_bufferSizeYetToRead = 0;
	}
	//else
	//{
	//	m_bufferSizeYetToRead -= size;
	//}
}
return;
QF_STACK_POP
}



void FASTParser::readFromStream( int m_socket) throw ( SocketRecvFailed )
{QF_STACK_PUSH(FASTParser::readFromStream)
// LENGTH + MAP + TEMPLATE + FIELDS . . .
//Group = COUNT + MAP + TEMPLATEID
//Yes, we can read without blocking
if (m_bufferSizeYetToRead == 0)
{
	while ( m_lenSizeYetToRead < 5 )
	{
		int size = recv( m_socket, m_sockbuffer + m_lenSizeYetToRead, 1, 0 );
		//fprintf(stdout, m_sockbuffer + m_lenSizeYetToRead, size );
		if ( size <= 0 )
		{
			if ( size == -1 ) return;
			throw SocketRecvFailed( size );
		}
		if ((unsigned char)m_sockbuffer[m_lenSizeYetToRead] >= STOP_BIT)
		{
			m_sockbuffer[m_lenSizeYetToRead] &= VALUE_BIT;
			m_lenSizeYetToRead++;
			break;
		}
		m_lenSizeYetToRead++;
	}
	if ( m_lenSizeYetToRead > 4 )
	throw "Overlong for the message length";

	m_bufferSize = 0 - ((m_sockbuffer [0] & 0x00) != 0);

	for (int icnt = 0; icnt < m_lenSizeYetToRead; icnt ++)
	m_bufferSize = m_bufferSizeYetToRead = (m_bufferSizeYetToRead << 7) | m_sockbuffer [icnt];
	m_lenSizeYetToRead = 0;
}

if ( m_bufferSizeYetToRead )
{
	int size = recv( m_socket, m_sockbuffer + m_bufferSize - m_bufferSizeYetToRead, m_bufferSizeYetToRead, 0 );
	if ( size <= 0 )
	{
		if ( size == -1 ) return;
		throw SocketRecvFailed( size );
	}
	if ( size == m_bufferSizeYetToRead )
	{
		Locker l( iq_mutex );
		{
			iq.push_back(iMsg(m_sockbuffer, m_bufferSizeYetToRead ));
		}
		m_bufferSizeYetToRead = 0;
	}
	else
	{
		m_bufferSizeYetToRead -= size;
	}
}
return;
QF_STACK_POP
}

void FASTParser::writeMessage( const std::string& str ) throw ( MessageParseError )
{
FIX::Message msg(str, *m_dataDictionary, true);
if (oFast.encode_message (eFAST_BASE_TID) < 0)
return;

oFast.reset_presence_map();
FIX::MsgType msgType;
msg.getHeader().getField( msgType );
if ( strchr( "", msgType.getValue().c_str() [ 0 ] ) )
{
	throw "MsgType is missing";
}

Msg2TemplateId::iterator ii = m_Message2TemplateId->find(msgType);
if ( ii == m_Message2TemplateId->end())
throw "Error, please define templateID";

int tid = ii->second;
oFast.encode_u32 (eFAST_MSG_TYPE, tid);
FastTagVector tags = m_dataDictionary->getFieldTag( tid );

if ( tid != 16002 && tid != 16003) //Hello Message
{
	//encodeTags( eFAST_HDR_TEMPLATE, tagvalues );
}

encodeTags( tid, msg );

if ( tid != 16002 && tid != 16003) //Hello Message
{
	//encodeTags( eFAST_TRL_TEMPLATE, tagvalues );
}

if (oFast.encode_message_end (eFAST_BASE_TID) < 0)
return;
char* pbuffer = NULL;
unsigned int iMsgLen = 0;
oFast.get_codec_output(reinterpret_cast<u8**>(&pbuffer), &iMsgLen );
iMsg message( pbuffer, iMsgLen );
m_sendQueue.push_back( message );

}

bool FASTParser::writeToStream( int m_socket, const sockaddr_in &addr) throw ( SocketRecvFailed )
{
const iMsg& msg = m_sendQueue.front();
unsigned char pSize[5];
int iStartPos = oFast.decode_message_length (eFAST_MSG_LEN, msg.length(), pSize);
if (m_sendLength == 0)
{
	int hdr = sendto( m_socket, reinterpret_cast<char*>(pSize), iStartPos, 0,(const struct sockaddr*) &addr, sizeof(addr) );
}
int result = sendto
( m_socket, msg.c_str() + m_sendLength, msg.length() - m_sendLength, 0, (const struct sockaddr*)&addr, sizeof(addr) );

if( result > 0 )
m_sendLength += result;

if( m_sendLength == msg.length() )
{
	m_sendLength = 0;
	m_sendQueue.pop_front();
}
return !m_sendQueue.size();
}


bool FASTParser::writeToStream( int m_socket) throw ( SocketRecvFailed )
{
const iMsg& msg = m_sendQueue.front();
unsigned char pSize[5];
int iStartPos = oFast.decode_message_length (eFAST_MSG_LEN, msg.length(), pSize);
if (m_sendLength == 0)
{
	int hdr = send ( m_socket, reinterpret_cast<char*>(pSize), iStartPos, 0 );
}
int result = send
( m_socket, msg.c_str() + m_sendLength, msg.length() - m_sendLength, 0 );

if( result > 0 )
m_sendLength += result;

if( m_sendLength == msg.length() )
{
	m_sendLength = 0;
	m_sendQueue.pop_front();
}
return !m_sendQueue.size();
}

void FASTParser::encodeTags(int tid, const FIX::Message &msg, int groupCount)
{
FastTagVector tags = m_dataDictionary->getFieldTag( tid );
u32 ku = 0;
i32 k = 0;
double d = 0;
i64 k64 = 0;
u64 ku64 = 0;
u8 v[50];
u8 *data;
std::vector<std::string> KeyValue;

for ( FastTagVector::iterator ii = tags.begin(); ii != tags.end(); ii++ )
{
	if ( ii->m_num == 10 || ii->m_num == 9 || ii->m_num == 9999)
	{
		continue;
	}
	ii->m_value = "";
	bool isFieldSet = false;
	if ( groupCount < 0 )
	{
		if( msg.isHeaderField(ii->m_num) && msg.getHeader().isSetField(ii->m_num) )
		{
			ii->m_value = msg.getHeader().getField(ii->m_num);
			isFieldSet = true;
		}
		else if( msg.isTrailerField(ii->m_num) && msg.getTrailer().isSetField(ii->m_num) )
		{
			ii->m_value = msg.getTrailer().getField(ii->m_num);
			isFieldSet = true;
		}
		else if ( msg.isSetField( ii->m_num) )
		{
			ii->m_value = msg.getField(ii->m_num);
			isFieldSet = true;
		}
	}
	else
	{
		FIX::Group g( tid, 99);

		if ( msg.hasGroup( groupCount , tid ) )
		{
			msg.getGroup(groupCount + 1 , tid, g);
			if ( g.isSetField( ii->m_num) )
			{
				ii->m_value = g.getField(ii->m_num);
				isFieldSet = true;
			}
		}
	}

	if ( !isFieldSet )
	{
		oFast.set_presence_map_x (ii->m_tag, ii->m_type);//need to set map here
		continue;
	}
	memset(v, '0', sizeof(v));
	switch( ii->m_type )
	{
		case eFAST_TYPE_ASCII:
		data = reinterpret_cast<u8*>(const_cast<char*>(ii->m_value.c_str()));
		oFast.encode_string (ii->m_tag, data, (int) strnlen ((char*) data, ii->m_value.length()));
		break;
		case eFAST_TYPE_I32:
		k = atoi(ii->m_value.c_str());
		oFast.encode_i32 (ii->m_tag, k);
		break;
		case eFAST_TYPE_U32:
		ku = atoi(ii->m_value.c_str());
		oFast.encode_u32 (ii->m_tag, ku);
		break;
		case eFAST_TYPE_GROUP:
		ku = atoi(ii->m_value.c_str());
		oFast.encode_group_count (ii->m_tag, ku);
		if ( ku )
		{
			for ( unsigned int i = 0; i < ku; i++ )
			{
				FASTGroup group;
				oFast.backup_group(group);
				u32 templateID = 0;
				if ( ii->get_ref_tid() == "none" )
				{
					//oFast.encode_u32 ( eFAST_MSG_TYPE, atoi(ii->get_ref_tid().c_str()) );
				}
				else
				{
					templateID = atoi(ii->get_ref_tid().c_str());
					oFast.encode_u32 ( eFAST_MSG_TYPE, templateID );
				}
				encodeTags( ii->get_num(), msg, i );
				oFast.restore_group(group);
			}
		}
		break;
		case eFAST_TYPE_DECMIAL:
		d = atof(ii->m_value.c_str());
		oFast.encode_double(ii->m_tag, d);
		sprintf(reinterpret_cast<char*>(v), "%f\0", d );
		ii->m_value = reinterpret_cast<char*>(v);
		break;
		case eFAST_TYPE_UNICODE:
		data = reinterpret_cast<u8*>(const_cast<char*>(ii->m_value.c_str()));
		oFast.encode_string (ii->m_tag, data, (int) strnlen ((char*) data, ii->m_value.length()));
		break;
		case eFAST_TYPE_I64:
		k64 = atol(ii->m_value.c_str());
		oFast.encode_i64 (ii->m_tag, k64);
		break;
		case eFAST_TYPE_U64:
		ku64 = atol(ii->m_value.c_str());
		oFast.encode_u64 (ii->m_tag, ku64);
		break;
		default:
		break;
	}
}
}
void FASTParser::encodeTags(int tid, std::map<int, std::string> tagvalues)
{
FastTagVector tags = m_dataDictionary->getFieldTag( tid );
u32 ku = 0;
i32 k = 0;
double d = 0;
i64 k64 = 0;
u64 ku64 = 0;
u8 v[50];
u8 *data;
std::vector<std::string> KeyValue;

for ( FastTagVector::iterator ii = tags.begin(); ii != tags.end(); ii++ )
{
	if ( ii->m_num == 10 || ii->m_num == 9 || ii->m_num == 9999)
	{
		continue;
	}
	std::map<int, std::string>::iterator i = tagvalues.find(ii->m_num);
	if ( i == tagvalues.end() )
	{
		oFast.set_presence_map_x (ii->m_tag, ii->m_type);//need to set map here
		continue;
	}
	else
	{
		ii->m_value = i->second;
	}
	memset(v, '0', sizeof(v));
	switch( ii->m_type )
	{
		case eFAST_TYPE_ASCII:
		data = reinterpret_cast<u8*>(const_cast<char*>(ii->m_value.c_str()));
		oFast.encode_string (ii->m_tag, data, (int) strnlen ((char*) data, ii->m_value.length()));
		break;
		case eFAST_TYPE_I32:
		k = atoi(ii->m_value.c_str());
		oFast.encode_i32 (ii->m_tag, k);
		break;
		case eFAST_TYPE_U32:
		ku = atoi(ii->m_value.c_str());
		oFast.encode_u32 (ii->m_tag, ku);
		break;
		case eFAST_TYPE_GROUP:
		ku = atoi(ii->m_value.c_str());
		oFast.encode_group_count (ii->m_tag, ku);
		if ( ku )
		{
			for (unsigned int i = 0; i < ku; i++ )
			{
				FASTGroup group;
				oFast.backup_group(group);
				u32 templateID = 0;
				if ( ii->get_ref_tid() == "none" )
				{
					//oFast.encode_u32 ( eFAST_MSG_TYPE, atoi(ii->get_ref_tid().c_str()) );
				}
				else
				{
					templateID = atoi(ii->get_ref_tid().c_str());
					oFast.encode_u32 ( eFAST_MSG_TYPE, templateID );
				}
				encodeTags( ii->get_num(), tagvalues );
				oFast.restore_group(group);
			}
		}
		break;
		case eFAST_TYPE_DECMIAL:
		d = atof(ii->m_value.c_str());
		oFast.encode_double(ii->m_tag, d);
		sprintf(reinterpret_cast<char*>(v), "%f\0", d );
		ii->m_value = reinterpret_cast<char*>(v);
		break;
		case eFAST_TYPE_UNICODE:
		data = reinterpret_cast<u8*>(const_cast<char*>(ii->m_value.c_str()));
		oFast.encode_string (ii->m_tag, data, (int) strnlen ((char*) data, ii->m_value.length()));
		break;
		case eFAST_TYPE_I64:
		k64 = atol(ii->m_value.c_str());
		oFast.encode_i64 (ii->m_tag, k64);
		break;
		case eFAST_TYPE_U64:
		ku64 = atol(ii->m_value.c_str());
		oFast.encode_u64 (ii->m_tag, ku64);
		break;
		default:
		break;
	}
}
}
void FASTParser::reset( void )
{
for(TemplateId2Msg::iterator ii = m_TemplateId2Message->begin(); ii != m_TemplateId2Message->end(); ii++)
{
	resetTemplate ( ii->first );
}
}

void FASTParser::resetTemplate(int tid)
{
FastTagVector tags = m_dataDictionary->getFieldTag( tid );
for ( FastTagVector::iterator ii = tags.begin(); ii != tags.end(); ii++ )
{
	if ( ii->m_value == "none" )
	{
		ii->m_value = "";
		continue;
	}
	switch( ii->m_type )
	{
		case eFAST_TYPE_ASCII:
		iFast.set (ii->m_tag, reinterpret_cast<u8*>(const_cast<char*>(ii->m_value.c_str())), ii->m_value.length());
		oFast.set (ii->m_tag, reinterpret_cast<u8*>(const_cast<char*>(ii->m_value.c_str())), ii->m_value.length());
		break;
		case eFAST_TYPE_I32:
		iFast.set( ii->m_tag, atoi(ii->m_value.c_str()) );
		oFast.set( ii->m_tag, atoi(ii->m_value.c_str()) );
		break;
		case eFAST_TYPE_U32:
		iFast.set( ii->m_tag, (u32) atoi(ii->m_value.c_str()) );
		oFast.set( ii->m_tag, (u32) atoi(ii->m_value.c_str()) );
		break;
		case eFAST_TYPE_GROUP:
		resetTemplate(ii->m_num);
		break;
		case eFAST_TYPE_DECMIAL:
		iFast.set( ii->m_tag, (double) atof(ii->m_value.c_str()) );
		oFast.set( ii->m_tag, (double) atof(ii->m_value.c_str()) );
		break;
		case eFAST_TYPE_UNICODE:
		iFast.set( ii->m_tag, reinterpret_cast<u8*>(const_cast<char*>(ii->m_value.c_str())), ii->m_value.length() );
		oFast.set( ii->m_tag, reinterpret_cast<u8*>(const_cast<char*>(ii->m_value.c_str())), ii->m_value.length() );
		break;
		case eFAST_TYPE_I64:
		iFast.set( ii->m_tag, (i64) atol( ii->m_value.c_str() ) );
		oFast.set( ii->m_tag, (i64) atol( ii->m_value.c_str() ) );
		break;
		case eFAST_TYPE_U64:
		iFast.set( ii->m_tag, (u64) atol( ii->m_value.c_str() ) );
		oFast.set( ii->m_tag, (u64) atol( ii->m_value.c_str() ) );
		break;
		default:
		break;
	}
}
}

}
